import time
from multiprocessing import Process, Pool


# 吃饭任务
def eat(name):
    for i in range(6):
        print(f'{name}正在吃东西...')
        time.sleep(0.3)


# 做作业任务
def work():
    for i in range(6):
        print('正在学习...')
        time.sleep(0.3)


# 玩游戏任务
def game():
    for i in range(6):
        print('正在玩游戏...')


if __name__ == '__main__':
    # 创建一个进程池 里面最多有2个进程
    pool = Pool(2)

    # # apply() 是阻塞的 （主进程阻塞的，程序先执行process_pool1进程，执行完成之后，再执行process_pool2进程，最后主进程【main】关闭）
    # process_pool1 = pool.apply(eat,('张三',))
    # # apply()可以串参数的，第一个参数是函数，第二个参数是元组，如果元组参数中只有一个元素，要加,
    # process_pool2 = pool.apply(work)


    # apply_async()是异步的，线程池中的 process_pool1 process_pool2 俩线程异步执行，
    process_pool1 = pool.apply_async(eat,('张三',))
    process_pool2 = pool.apply_async(work)

    process_pool3 = pool.apply_async(game) # 进程中最大进程数只有两个进程，都被前面俩占用了，等释放出来一个进程，此进程才可以被执行

    # 进程池pool 中子进程的的管理者是进程池主进程，而不是__main__ 主进程，
    # 进程池中的子进程要 apply_async()方法的进程，要被唤醒开始执行任务前，必须调用 pool.close() pool.join() 才可以。
    pool.close() # 关闭进程池
    pool.join()

    # 2. pool.close()的作用
    # 功能：禁止进程池接收新任务（但已提交的任务会继续执行）。
    # 必要性：若未调用close()直接join()，可能导致死锁（新任务无法提交，旧任务未完成）。
    # 3.pool.join()的作用
    # 功能：阻塞主进程（如__main__），直到进程池中所有任务完成。
    # 底层机制：内部调用wait()方法监控子进程状态，确保process_pool3这类排队任务被执行完毕。

    # 总结：
    # 1.进程的执行顺序是 process_pool1 process_pool2 并行执行（异步执行）
    # 2.process_pool1 process_pool2 当中一个执行完之后 process_pool3 才开始进入进程池，开始执行。
    # 3.pool.join() 内部调用 wait()方法监控子进程状态，
    # 4.等待子进程的任务全部执行完毕。pool 中进程全部执行完毕，
    # 5.__main__ 主进程执行 执行完毕